//
//  CoGeRandomPlugIn.m
//  CoGeRandom
//
//  Created by Tamas Nagy on 11/6/09.
//  Copyright (c) 2009 __MyCompanyName__. All rights reserved.
//

/* It's highly recommended to use CGL macros instead of changing the current context for plug-ins that perform OpenGL rendering */
#import <OpenGL/CGLMacro.h>

#import "CoGeRandomPlugIn.h"

#define	kQCPlugIn_Name				@"CoGeRandom"
#define	kQCPlugIn_Description		@"Random generator"

@implementation CoGeRandomPlugIn

/*
Here you need to declare the input / output properties as dynamic as Quartz Composer will handle their implementation
@dynamic inputFoo, outputBar;
*/

@dynamic inputCount, inputNewNumber, inputReset, outputNumber;

+ (NSDictionary*) attributes
{
	/*
	Return a dictionary of attributes describing the plug-in (QCPlugInAttributeNameKey, QCPlugInAttributeDescriptionKey...).
	*/
	
	return [NSDictionary dictionaryWithObjectsAndKeys:kQCPlugIn_Name, QCPlugInAttributeNameKey, kQCPlugIn_Description, QCPlugInAttributeDescriptionKey, nil];
}

+ (NSDictionary*) attributesForPropertyPortWithKey:(NSString*)key
{
	
	
	if([key isEqualToString:@"inputCount"])
		
        return [NSDictionary dictionaryWithObjectsAndKeys:
				QCPortTypeNumber, QCPortAttributeTypeKey,
				@"Count", QCPortAttributeNameKey,
				nil];

	if([key isEqualToString:@"inputNewNumber"])
		
        return [NSDictionary dictionaryWithObjectsAndKeys:
				QCPortTypeBoolean, QCPortAttributeTypeKey,
				[NSNumber numberWithInt:0], QCPortAttributeDefaultValueKey,
				@"New Number", QCPortAttributeNameKey,
				nil];

	if([key isEqualToString:@"inputReset"])
		
        return [NSDictionary dictionaryWithObjectsAndKeys:
				QCPortTypeBoolean, QCPortAttributeTypeKey,
				[NSNumber numberWithInt:0], QCPortAttributeDefaultValueKey,
				@"Reset", QCPortAttributeNameKey,
				nil];

	if([key isEqualToString:@"outputNumber"])
		
        return [NSDictionary dictionaryWithObjectsAndKeys:
				QCPortTypeNumber, QCPortAttributeTypeKey,				
				nil];
	
	return nil;
}

+ (QCPlugInExecutionMode) executionMode
{
	/*
	Return the execution mode of the plug-in: kQCPlugInExecutionModeProvider, kQCPlugInExecutionModeProcessor, or kQCPlugInExecutionModeConsumer.
	*/
	
	return kQCPlugInExecutionModeProcessor;
}

+ (QCPlugInTimeMode) timeMode
{
	/*
	Return the time dependency mode of the plug-in: kQCPlugInTimeModeNone, kQCPlugInTimeModeIdle or kQCPlugInTimeModeTimeBase.
	*/
	
	return kQCPlugInTimeModeNone;
}

- (id) init
{
	if(self = [super init]) {
		/*
		Allocate any permanent resource required by the plug-in.
		*/
	}
	
	return self;
}

- (void) finalize
{
	/*
	Release any non garbage collected resources created in -init.
	*/
	
	[super finalize];
}

- (void) dealloc
{
	/*
	Release any resources created in -init.
	*/
	
	[super dealloc];
}

@end

@implementation CoGeRandomPlugIn (Execution)

- (BOOL) startExecution:(id<QCPlugInContext>)context
{
	/*
	Called by Quartz Composer when rendering of the composition starts: perform any required setup for the plug-in.
	Return NO in case of fatal failure (this will prevent rendering of the composition to start).
	*/
	
	return YES;
}

- (void) enableExecution:(id<QCPlugInContext>)context
{
	/*
	Called by Quartz Composer when the plug-in instance starts being used by Quartz Composer.
	*/

	workArray = nil;
}

- (BOOL) execute:(id<QCPlugInContext>)context atTime:(NSTimeInterval)time withArguments:(NSDictionary*)arguments
{
	/*
	Called by Quartz Composer whenever the plug-in instance needs to execute.
	Only read from the plug-in inputs and produce a result (by writing to the plug-in outputs or rendering to the destination OpenGL context) within that method and nowhere else.
	Return NO in case of failure during the execution (this will prevent rendering of the current frame to complete).
	
	The OpenGL context for rendering can be accessed and defined for CGL macros using:
	CGLContextObj cgl_ctx = [context CGLContextObj];
	*/
	
	if (([self didValueForInputKeyChange:@"inputCount"]) || ([self didValueForInputKeyChange:@"inputReset"])) {
	
		//NSLog(@"build the array...");
		
		if (workArray != nil) [workArray release];
		
		workArray = [[NSMutableArray alloc] initWithCapacity:self.inputCount];
		
		for (int i=0;i<self.inputCount;i++) {
		
			[workArray insertObject:[NSNumber numberWithInt:i] atIndex:i];
		}
		
	}
	
	if (([self didValueForInputKeyChange:@"inputNewNumber"]) && (self.inputNewNumber == YES)) {
	
		//NSLog(@"array count: %d", [workArray count]); 
		int i;
		
		if ([workArray count] > 0) {

			i = random() % [workArray count];

		} else {
		
			i = 0;
		
		}
		
		//NSLog(@"random index: %d", i);
		
		
		if ([workArray count] > 0) {
		
			self.outputNumber = [[NSNumber numberWithInt:[[workArray objectAtIndex:i] intValue]] doubleValue];
			
			[workArray removeObjectAtIndex:i];
			
		} else {
			
			self.outputNumber = -1;
		
		}
		
	}
	
	
	return YES;
}

- (void) disableExecution:(id<QCPlugInContext>)context
{
	/*
	Called by Quartz Composer when the plug-in instance stops being used by Quartz Composer.
	*/
	
	//need the release workArray here. Thanks for poiting this is Cwright!
	if (workArray != nil) [workArray release];
	
}

- (void) stopExecution:(id<QCPlugInContext>)context
{
	/*
	Called by Quartz Composer when rendering of the composition stops: perform any required cleanup for the plug-in.
	*/
	
	
}

@end
